﻿using System;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
using System.Collections;

/// <summary>
/// Author:gouzhun
/// Spine动画的相关修改插件
/// 
/// </summary>
public class SpineTools : EditorWindow
{
	private List<Material> mats;

	private List<Material> spineMats;

	private List<Material> spineLitMats;

	private List<Material> spineAlphaMats;

	private Vector2 mScroll;

	private Vector2 rightScroll;

	private Vector2 endScroll;

	private string alphaPath = "Assets/_AlphaFile";

	private string searchPath = string.Empty;
	private List<Texture2D> rgbTexList;
	private List<Texture2D> alphaTexList;

	[MenuItem("Coser/Spine Tools")]
	public static void InitWindow()
	{
		EditorWindow.GetWindow<SpineTools>();

	}

	public SpineTools()
	{
		mats = new List<Material>();
		spineMats = new List<Material>();
		spineLitMats = new List<Material>();
		spineAlphaMats = new List<Material>();
	}

	private void OnGUI()
	{
		GUI.color = Color.cyan;
		GUILayout.Label("搜索路径（需要自动生成的路径，以”；“来分割多个路径）："); searchPath = GUILayout.TextArea(searchPath);
		GUI.color = Color.white;
		if (GUILayout.Button("Find all materials in asset folder"))
		{
			FindAllMaterials();
		}

		GUI.color = Color.yellow;
		if (GUILayout.Button("Find the given path's material"))
		{
			FindAllMaterials(searchPath);
		}

		GUI.color = Color.yellow;
		if (GUILayout.Button("Change Spine Material to PNG8 Version"))
		{
			ChangeToPNG8Version();
		}



		GUI.color = Color.green;
		if (GUILayout.Button("Generate the material's texture"))
		{
			ChangeOrGenerateToPNG8Version();
		}

		GUI.color = Color.red;
		if (GUILayout.Button("RGBA32 -> RGBA16"))
		{
			ChangeRGBAToRGBA16();
		}

		GUI.color = Color.yellow;
		if (GUILayout.Button("Change All Texture's format"))
		{
			GetTextures();

			ChangeTexturesSettings(rgbTexList, TextureImporterFormat.RGB16);

			ChangeTexturesSettings(alphaTexList, TextureImporterFormat.Alpha8);
		}

		if (GUILayout.Button("Delete unused image"))
		{
			GetTextures();
			DeleteUnusedTexture(rgbTexList);
		}

		GUI.color = Color.cyan;
		GUILayout.Label("保存路径（切好的Alpha8图片存储路径---父文件夹是Assets,需要写这个）："); alphaPath = EditorGUILayout.TextArea(alphaPath);

		GUI.color = Color.white;
		EditorGUILayout.BeginHorizontal();

		//all material
		EditorGUILayout.BeginVertical();
		EditorGUILayout.LabelField("All Material count:" + mats.Count.ToString());
		mScroll = EditorGUILayout.BeginScrollView(mScroll);


		for (int i = 0; i < mats.Count; i++)
		{
			var mat = mats[i];
			if (mat)
			{
				mats[i] = EditorGUILayout.ObjectField(mats[i], typeof(Material), false) as Material;
			}

		}
		EditorGUILayout.EndScrollView();
		EditorGUILayout.EndVertical();

		//skeleton
		EditorGUILayout.BeginVertical();
		EditorGUILayout.LabelField("All Spine materials count:" + spineMats.Count.ToString());
		rightScroll = EditorGUILayout.BeginScrollView(rightScroll);


		for (int j = 0; j < spineMats.Count; j++)
		{
			var spineMat = spineMats[j];
			if (spineMat)
			{
				spineMats[j] = EditorGUILayout.ObjectField(spineMats[j], typeof(Material), false) as Material;
			}

		}
		EditorGUILayout.EndScrollView();
		EditorGUILayout.EndVertical();

		//skeleton lit
		EditorGUILayout.BeginVertical();
		EditorGUILayout.LabelField("All Spine Lit materials count:" + spineLitMats.Count.ToString());
		endScroll = EditorGUILayout.BeginScrollView(endScroll);


		for (int j = 0; j < spineLitMats.Count; j++)
		{
			var spineMat = spineLitMats[j];
			if (spineMat)
			{
				spineLitMats[j] = EditorGUILayout.ObjectField(spineLitMats[j], typeof(Material), false) as Material;
			}

		}
		EditorGUILayout.EndScrollView();
		EditorGUILayout.EndVertical();

		
		//skeleton_alpha
		EditorGUILayout.BeginVertical();
		EditorGUILayout.LabelField("All Spine_Alpha materials count:" + spineAlphaMats.Count.ToString());
		endScroll = EditorGUILayout.BeginScrollView(endScroll);


		for (int j = 0; j < spineAlphaMats.Count; j++)
		{
			var spineMat = spineAlphaMats[j];
			if (spineMat)
			{
				spineAlphaMats[j] = EditorGUILayout.ObjectField(spineAlphaMats[j], typeof(Material), false) as Material;
			}

		}
		EditorGUILayout.EndScrollView();
		EditorGUILayout.EndVertical();
		EditorGUILayout.EndHorizontal();
	}

	private void ChangeRGBAToRGBA16()
	{
		for (int i = 0; i < spineMats.Count; i++)
		{
			var material = spineMats[i];
			var mainTex = material.mainTexture as Texture2D;
			if (!mainTex)
			{
				Debug.LogError("Material's main texture is null");
			}
			else
			{
				var path = AssetDatabase.GetAssetPath(mainTex);
				if(path != null)
				{
				ChangeTextureSettings.SetupImporter(TextureImporterFormat.ARGB16, 100,path,mainTex,TextureImporterNPOTScale.None,TextureWrapMode.Repeat);
				}
				else
				{
					Debug.LogError("Find null at:" + mainTex.name);
				}
			}
			EditorUtility.DisplayProgressBar("Working~~", material.name, i / ((float)mats.Count));
		}
		EditorUtility.ClearProgressBar();
	}

	private void ChangeToPNG8Version()
	{
		ChangeMaterials(spineMats, "Spine/Skeleton_alpha", alphaPath);
		ChangeMaterials(spineLitMats, "Spine/Skeleton Lit_alpha", alphaPath);
	}

	private void ChangeOrGenerateToPNG8Version()
	{
		ChangeMaterials(spineMats, "Spine/Skeleton_alpha", alphaPath, true);
		ChangeMaterials(spineLitMats, "Spine/Skeleton Lit_alpha", alphaPath, true);
	}

	private void ChangeMaterials(List<Material> mats, string shaderName, string parentPath, bool autoGenerate = false)
	{
		rgbTexList = new List<Texture2D>();
		alphaTexList = new List<Texture2D>();
		for (int index = 0; index < mats.Count; index++)
		{
			var material = mats[index];
			var maintex = material.mainTexture as Texture2D;
			var alphaTex = GetAlphaTexture(maintex, parentPath);
			if (!maintex)
			{
				Debug.LogError("Material's main texture is null");
			}
			else
			{
				if (alphaTex)
				{
					SetShaderAndTexture(shaderName, material, maintex, alphaTex);
				}
				else
				{
					if (autoGenerate)
					{
						var texList = ConvertImage.SplitTextureToAlpha8AndRGB24(maintex, parentPath);
#if UNITY_ANDROID
						var rgbTex = ConvertImage.ImportTexture2D(texList[0], TextureImporterFormat.ETC_RGB4);
#elif UNITY_IPHONE || UNITY_IOS || UNITY
						var rgbTex = ConvertImage.ImportTexture2D(texList[0], TextureImporterFormat.PVRTC_RGB4);
#else
						var rgbTex = ConvertImage.ImportTexture2D(texList[0], TextureImporterFormat.RGBA32);
						Debug.LogError("平台不对");
#endif
						alphaTex = ConvertImage.ImportTexture2D(texList[1], TextureImporterFormat.Alpha8);
						SetShaderAndTexture(shaderName, material, rgbTex, alphaTex);
						Debug.Log("<color=green>Cannot find material's texture,Generated for:</color>" + material.name);

						rgbTexList.Add(rgbTex);
						alphaTexList.Add(alphaTex);

					}
					else
					{
						Debug.Log("<color=red>Cannot find material's texture,Ignore:</color>" + material.name);
					}
				}
			}
			EditorUtility.DisplayProgressBar("Working~~", material.name, index / ((float)mats.Count));
		}

		EditorUtility.ClearProgressBar();



		ChangeTexturesSettings(alphaTexList, TextureImporterFormat.ETC_RGB4);

		ChangeTexturesSettings(alphaTexList, TextureImporterFormat.Alpha8);
	}


	private void GetTextures()
	{
		rgbTexList = new List<Texture2D>();
		alphaTexList = new List<Texture2D>();
		for (int index = 0; index < spineAlphaMats.Count; index++)
		{
			var material = spineAlphaMats[index];
			var maintex = material.mainTexture as Texture2D;
			var alphaTex = material.GetTexture("_AlphaTex") as Texture2D;
			if (!maintex || !alphaTex)
			{
				Debug.LogError("Material's main texture or alpha texture is null at :" + material.name);
			}
			else
			{
				rgbTexList.Add(maintex);
				alphaTexList.Add(alphaTex);
			}

		}

		Debug.Log("Get RGB texture:" + rgbTexList.Count);
		Debug.Log("Get Alpha texture:" + alphaTexList.Count);
	}

	private static void ChangeTexturesSettings(List<Texture2D> alphaTexList, TextureImporterFormat format, int quality = 100)
	{
		for (int index = 0; index < alphaTexList.Count; index++)
		{
			var texture2D = alphaTexList[index];
			var path = AssetDatabase.GetAssetPath(texture2D);
			EditorUtility.DisplayCancelableProgressBar("Changing~~", path, index / (float)alphaTexList.Count);
			Debug.Log("TextureFormat切换成功：" + path);
			ChangeTextureSettings.SetupImporter(format, quality, path, texture2D, TextureImporterNPOTScale.None);
		}
		EditorUtility.ClearProgressBar();
	}

	private static void DeleteUnusedTexture(List<Texture2D> texList )
	{
		for (int index = 0; index < texList.Count; index++)
		{
			var texture2D = texList[index];
			var path = AssetDatabase.GetAssetPath(texture2D);

			var parentPath = Directory.GetParent(path);
			var fileName = Path.GetFileNameWithoutExtension(path);

			var pngPath = Path.Combine(parentPath.FullName, fileName) + ".png";

			if (File.Exists(pngPath))
			{
				File.Delete(pngPath);
				//AssetDatabase.DeleteAsset(pngPath);
				Debug.Log("Delete at" + pngPath);
			}

			EditorUtility.DisplayCancelableProgressBar("deleting~~", pngPath, index / (float)texList.Count);
		 
		}
		EditorUtility.ClearProgressBar();
	}


	private static void SetShaderAndTexture(string shaderName, Material material, Texture2D maintex, Texture2D alphaTex)
	{
		material.shader = Shader.Find(shaderName);
		material.SetTexture("_MainTex", maintex);
		material.SetTexture("_AlphaTex", alphaTex);
	}



	private Texture2D GetAlphaTexture(Texture tex, string parentPath)
	{
		var path = AssetDatabase.GetAssetPath(tex);

		var fileName = Path.GetFileName(path);
		if (fileName != null)
		{
			var filePath = Path.Combine(parentPath, "alpha_" + fileName);
			if (File.Exists(filePath))
			{
				Debug.Log("Load Texture At:" + filePath);
				return AssetDatabase.LoadAssetAtPath(filePath, typeof(Texture2D)) as Texture2D;
			}
		}
		else
		{
			Debug.Log("Can not find at:" + path);
		}
		return null;
	}

	private void FindAllMaterials(string searchInFolders = null)
	{
		mats.Clear();
		spineMats.Clear();
		spineLitMats.Clear();
		spineAlphaMats.Clear();

		string[] texGuids = null;

		if (searchInFolders != null)
		{
			var searchFolderArray = searchInFolders.Split(';');
			texGuids = AssetDatabase.FindAssets("t:Material", searchFolderArray);
		}
		else
		{
			texGuids = AssetDatabase.FindAssets("t:Material");
		}

		//var texs = Selection.GetFiltered(typeof (Texture2D), SelectionMode.DeepAssets);
		Debug.Log("Material Found:" + texGuids.Length);
		foreach (string texGuid in texGuids)
		{
			var assetpath = AssetDatabase.GUIDToAssetPath((texGuid));

			//	Debug.Log(texture2D.name +" path:" + assetpath);
			if (!string.IsNullOrEmpty(assetpath))
			{
				var mat = AssetDatabase.LoadAssetAtPath(assetpath, typeof(Material)) as Material;
				//TODO:filter condition
				if (mat != null)
				{
					mats.Add(mat);
					Debug.Log(mat.shader.name);
					if (mat.shader.name.ToLower() == "spine/skeleton")
					{
						spineMats.Add(mat);
					}

					if (mat.shader.name.ToLower() == "spine/skeleton lit")
					{
						spineLitMats.Add(mat);
					}

					if (mat.shader.name.ToLower() == "spine/skeleton_alpha")
					{
						spineAlphaMats.Add(mat);
					}
				}
			}
		}
	}
}
